// ----------------------------------------------------------------------------
// serialize_counted_pointer_member.cpp
// ----------------------------------------------------------------------------
#include <fw/base/serialize/serialize_counted_pointer_member.h>
#include <fw/base/serialize/serialize_compound_type.h>
#include <fw/base/serialize/serialize_scalar_value.h>
#include <fw/base/serialize/byte_reader.h>
#include <fw/base/serialize/byte_writer.h>
#include <fw/base/runtime/hash.h>
#include <fw/base/core/assertion.h>

namespace fw
{
	SerializeCountedPointerMember::SerializeCountedPointerMember(int count, Hash typeName, Hash countName)
	: SerializePointerMember(count, typeName)
	{
		m_countName = countName;
	}
	
	int SerializeCountedPointerMember::GetPointerCount(const char *scopeData, int index) const
	{
		int pointerCount = 1;
		
		const SerializeMember* countMember = GetScope()->FindMember(m_countName);
		if(countMember)
		{
			pointerCount = static_cast<int>(countMember->ReadScalarValue(scopeData).AsInt());
		}
		return pointerCount;
	}
	
	void SerializeCountedPointerMember::Write(ByteWriter& writer) const
	{
		uint8_t code = kByteCode_CountedPointer;
		
		if(GetCount()>1)
		{
			code |= kByteCodeFlag_Array;
		}
		
		if(m_countName)
		{
			code |= kByteCodeFlag_CountName;
		}
		
		writer.Write8	(code);
		writer.Write32	(GetTypeName());
		if(code & kByteCodeFlag_Array)
		{
			writer.Write16(GetCount());
		}
		if(code & kByteCodeFlag_CountName)
		{
			writer.Write32(m_countName);
		}
	}
	
	SerializeCountedPointerMember* SerializeCountedPointerMember::ReadNew(ByteReader& reader)
	{
		size_t rollBack = reader.Tell();
		SerializeCountedPointerMember* member = nullptr;
		
		uint8_t code = reader.Read8();
		
		if((code & kByteCode_Mask) == kByteCode_CountedPointer)
		{
			int count = 1;
			Hash countName;
			
			Hash typeName = reader.Read32();
			if(code & kByteCodeFlag_Array)
			{
				count = reader.Read16();
			}
			if(code & kByteCodeFlag_CountName)
			{
				countName = reader.Read32();
			}
			member = new SerializeCountedPointerMember(count, typeName, countName);
		}
		
		if(!member)
		{
			reader.Seek(rollBack);
		}
		return member;
	}
	
	uint64_t SerializeCountedPointerMember::GetCheckSum(uint64_t basis) const
	{
		basis = SerializeMember::GetChecksum(basis);
		basis = HashValue64(m_countName, basis);
		return basis;
	}
	
} // namespace fw
